<?php

namespace App\Common\Model\Base\DataUnit;

use App\Common as com;
use App\Common\Model\Base\DataUnit\Cache as nameCache;
use App\Common\Model\Base\DataUnit as nameDataUnit;

class Cache extends nameDataUnit\Base {

	private bool $useCache = false;

	private ?string $cacheKeyName = null;

	private ?int $cacheExpire = null;

	private bool $force = false;

	/**
	 * @param string|bool $keyName [string]keyName [false]不使用缓存 [null]使用缓存
	 * @param int|null $expire 缓存过期时间 [null]永久 [3600][默认]
	 * @param bool $isForce 是否强制刷新缓存
	 * @return $this
	 */
	public function cache( $keyName = null, ?int $expire = 3600, bool $isForce = false ):self {
		if( $keyName === false ){
			$this->useCache = false;
			return $this;
		} elseif( ! $this->useCache ){
			$this->useCache = true;
		}
		//
		$this->cacheKeyName = $keyName === true ? null : $keyName;
		$this->cacheExpire = $expire;
		$this->force = $isForce;
		//
		return $this;
	}

	/**
	 * @param int|null $expire 缓存过期时间 [null]永久 [3600][默认]
	 * @return $this
	 */
	public function cacheExpire( ?int $expire = 3600 ):self {
		$this->cacheExpire = $expire;
		return $this;
	}

	/**
	 * 是否强制刷新缓存
	 * @param bool $isForce
	 * @return $this
	 */
	public function force( bool $isForce = true ):self {
		$this->force = $isForce;
		return $this;
	}


	/**
	 * @param nameDataUnit $dataUnit
	 * @param \Closure $fn 缓存不存在时执行闭包，缓存并返回闭包数据
	 * @return bool|mixed|string
	 * @throws
	 */
	public function get( nameDataUnit $dataUnit, \Closure $fn ) {
		if( ! $this->useCache ){
			return call_user_func( $fn );
		}
		//
		$cacheKey = $this->cacheKeyName;
		if( $cacheKey === null ){
			$cacheKey = $dataUnit->getFullSql();
			$dataUnit->goModelQueryCloneOfNew();
		}
		//
		$keyDb = com\Lib\Cache\KeyDB::use( $cacheKey );
		$data = $this->force ? false : $keyDb->get();
		// 缓存不存在则写入
		if( $data === false ){
			$data = call_user_func( $fn );
			if( $data !== null ){
				$keyDb->set( $data, $this->cacheExpire );
			} else{
				// 数据不存在，删除缓存
				$keyDb->del();
			}
		}
		//
		return $data;
	}

}
